//
//  AsteroidsLayer.m
//  Asteroids
//
// This is the CCLayer on which the game takes place. We draw everything on
// an OpenGL Layer.
//
// Created by Charles Kollar charles@kollar.com on 8/13/10 to serve as a
// "starter" app for an iPod/iPhone/iPad programming course.
//
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

// for arctan, sin, and cos...
#include "math.h"

// Import the interfaces
#import "AsteroidsLayer.h"
#import "ApplicationData.h"
#import "SaveScoreLayer.h"


//
// Things that you can do...
// 1) experiment with images rather than raster graphics.
// 2) add a score visible on a layer overlaid on the playing layer
// 3) add multiple space ships (one per iPod) using the blue tooth interface
// 4) add a 'high score' for the device or "globally" using http://www.cocoslive.net/



////
//// For Chupmunk Physics documentation see...
//// http://files.slembcke.net/chipmunk/release/ChipmunkLatest-Docs/
////
//// Many of the comments included in this file have been taken directly
//// from the (above) documentation.
////

/// NOTE: These variables need to be globals so that they can be accessed
/// by the Chipmunk Physics 'C' routines...

// Spaces in Chipmunk are the basic unit of simulation. You add rigid bodies,
// shapes and constraints to it and then step them forward through time.
cpSpace *space;

// The Chipmunk body associated with the space ship...
cpBody *shipBody;

// The Chipmunk colission shapes associated with fired missiles that are still 'alive'...
cpShape *missileShape[MAX_MISSILES];

// If this goes to zero after the init routine, then all of the asteroids have been destroyed.
int asteroidCount;


////
//// These are the routines that are used to work with shapes that are displayed
//// by the 'draw*' routines in this file. These are taken from Chipmunk Physics
//// but lack the checks for the convex manifold.
////


// The shape to draw for the body. It is found/placed in body->data...
static drawablePolyShape *newDrawablePolyShape(int numVerts, cpVect *verts) {
	drawablePolyShape *poly = cpcalloc(1, sizeof(cpPolyShape));
	poly->numVerts = numVerts;
	poly->verts = (cpVect *)cpcalloc(numVerts, sizeof(cpVect));
	
	for (int i=0; i<numVerts; i++) poly->verts[i] = verts[i];
	
	return poly;
}
static void freeDrawablePolyShape(drawablePolyShape *dps) {
	free(dps->verts);
	free(dps);
}
// Used by the iterator 'cpSpaceEachBody' to free any that exist in method 'dealloc'..
static void freeDrawablePolyShapeInBody(cpBody *b,  __attribute__ ((unused)) void *data) {
	drawablePolyShape *dps = (drawablePolyShape *)b->data;
	if (dps) freeDrawablePolyShape(dps);
}

////
//// Routines that create the objects that are seen on the screen...
////

///
/// Create the "Space Ship"...
static void newShip() {	
	// The verticies and multiplier for the "classic" asteroid space ship shape...
	// The mulriplier is used to adjust for the size on the screen.
	cpFloat sm = 1.0; // the size multiplier to make life easier if we want the ship to grow or shrink from the default size before constructing it
	// Use Inkscape. Begin deawing the ship centered at (0,0) (bottom left of the drawing)
	cpVect verts[] = {
		cpv(-15.0f*sm, 0.0f*sm),	// front tip
		cpv(15.0f*sm, 9.0f*sm),		// upper right
		cpv(10.0f*sm, 0.0f*sm),		// thrusters attach here
		cpv(15.0f*sm, -9.0f*sm)		// lower right
	};
	
	// Rigid Bodies: A rigid body holds the physical properties of an object. (mass, position, rotation, velocity, etc.)
	// It does not have a shape by itself.
	shipBody = cpBodyNew(SHIP_MASS, cpMomentForPoly(SHIP_MASS, (sizeof(verts)/sizeof(cpVect)), verts, cpvzero));
	CGSize wins = [[CCDirector sharedDirector] winSize];
	shipBody->p = cpv(wins.width/2,wins.height/2); // Place the center of the ship in the center of the window
	
	// This is what we will draw for this shape. We can't use a cpPolyShape because of the
	// "contect mainifold with a clockwise winding" policy imposition.
	drawablePolyShape *poly = newDrawablePolyShape((sizeof(verts)/sizeof(cpVect)), verts);
	shipBody->data = (cpDataPointer)poly;
	
	cpSpaceAddBody(space, shipBody);
	
	// The [colission] shape is the thing that is used to detect collisions. This needs to be a "convex manifold" with a clockwise winding.
	// The place where the thrusters attach to the space ship would cause this to be a "concave manifold". So, we need to remove
	// if from the collision shape. We put it at the center of the ship (more or less) with no offset.
	// Another way of doing this is to break the original shape down into three, but that would slow things down.
	cpVect coll_verts[] = {
		cpv(-15.0f*sm, 0.0f*sm), // front tip
		cpv(15.0f*sm, 9.0f*sm),	 // upper right
		cpv(15.0f*sm, -9.0f*sm)	 // lower right
	};
	
	// Collision Shapes: By attaching shapes to bodies, you can define the a body’s shape for the purposes of colission.
	// You can attach as many shapes to a single body as you need to in order to define a complex shape.
	// Shapes contain the surface properties of an object such as how much friction or elasticity it has.
	cpShape *shape = cpPolyShapeNew(shipBody, (sizeof(coll_verts)/sizeof(cpVect)), coll_verts, cpvzero);
	shape->collision_type = kColl_Ship;
	cpSpaceAddShape(space, shape);
}

static void fireMissile() {
	cpShape **shape = NULL;
	// See if there is a place for a new missile...
	for (int i=0; i<MAX_MISSILES; i++)
		if (missileShape[i] == NULL) {
			shape = &missileShape[i];
			break;
		}
	
	if (shape != NULL) {
		// Yes, there was space, so create it...

		// Calculate the moment of inertia for a hollow circle, r1 and r2 are the inner and outer diameters
		// in no particular order. (A solid circle has an inner diameter of 0)
		cpBody *missileBody = cpBodyNew(MISSILE_MASS, cpMomentForCircle(MISSILE_MASS, 0.0f, MISSILE_RADIUS, cpvzero));
		// Place the missile at the bow of the ship (e.g, at the end of the ship and at the same angle as the ship). 
		cpVect missilePosRelativeToShip = cpv((-15.0f-MISSILE_RADIUS)*cos(shipBody->a),(-15.0f-MISSILE_RADIUS)*sin(shipBody->a));
		missileBody->p = cpvadd(shipBody->p, missilePosRelativeToShip);
		cpSpaceAddBody(space, missileBody);
		
		*shape = cpCircleShapeNew(missileBody, MISSILE_RADIUS, cpvzero);
		(*shape)->collision_type = kColl_Missile;
		(*shape)->group = kColl_Missile;
		(*shape)->data = (cpDataPointer)MISSILE_STEP_LIFE; // number of 'step's that the missile lasts before hitting something
		cpSpaceAddShape(space, *shape);
		
		// now fire it...
		// Apply an impulse (in world coordinates) to the body at a point relative to the center of gravity (also in world coordinates).
		// An impules is just that, it is not an enduring force. See Chipmunk documentation for the distinction...
		cpVect shipUnitAxisVector = cpvnormalize(missilePosRelativeToShip); // unit vector of the axis of the ship
		// The impulse given to the missle should include the current velocity of the ship, and
		// also include a force along the axis vector of the ship (because it's being fired along that axis).
		cpVect missileImpulse = cpvadd(shipBody->v, cpvmult(shipUnitAxisVector, MISSILE_IMPULSE_MAGNITUDE));
		cpBodyApplyImpulse(missileBody, missileImpulse, cpvzero);
	}
}

static void newAsteroid(int splitCount, cpVect pos) {
	cpFloat splitCountF = (cpFloat)splitCount;
	
	cpFloat asteroidMass = 10.0f*splitCountF + (cpFloat)(rand()%100);
	cpFloat asteroidRadius = 7.0f*splitCountF + (cpFloat)(rand()%4);
	NSLog(@"newAsteroid splitCount=%d  mass=%f  radius=%f\n", splitCount, asteroidMass, asteroidRadius);
	
	// Calculate the moment of inertia for a hollow circle, r1 and r2 are the inner and outer diameters
	// in no particular order. (A solid circle has an inner diameter of 0)
	cpBody *asteroidBody = cpBodyNew(asteroidMass, cpMomentForCircle(asteroidMass, 0.0f, asteroidRadius, cpvzero));
	asteroidBody->p = pos;

	cpFloat sm = 0.5f*splitCountF; // the size multiplier
	// same basic shape, but get's smaller as the split ocunt approaches 0...
	cpVect verts[] = {
		cpvmult(cpv(-14.8f,3.8f), sm),
		cpvmult(cpv(-8.6f,12.6f), sm),
		cpvmult(cpv(5.8f,12.2f), sm),
		cpvmult(cpv(12.4f,4.6f), sm),
		cpvmult(cpv(10.2f,-3.2f), sm),
		cpvmult(cpv(13.4f,-7.6f), sm),
		cpvmult(cpv(5.7f,-6.8f), sm),
		cpvmult(cpv(-2.7f,-11.7f), sm),
		cpvmult(cpv(-9.5f,-5.6f), sm),
		cpvmult(cpv(-9.7f,1.9f), sm)
	};
	drawablePolyShape *poly = newDrawablePolyShape((sizeof(verts)/sizeof(cpVect)), verts);
	asteroidBody->data = (cpDataPointer)poly;
	
	cpSpaceAddBody(space, asteroidBody);
	
	// We will use a circle as a colission shape. For a circle, colissions are easy to compute.
	// We will attach a more interesting looking shape for display purposes...
	cpShape *shape = cpCircleShapeNew(asteroidBody, asteroidRadius, cpvzero);
	shape->collision_type = kColl_Asteroid;
	shape->group = kColl_Asteroid; // So if an asteroid runs into another asteroid, this is not recognized as a colission.
	shape->data = (cpDataPointer)splitCount; // Number of times that it can be shot and split before going away
	cpSpaceAddShape(space, shape);
	
	// send it off in some direction....
	cpFloat ang = rand()%6;
	// In keeping with the workings of the original asteroids game we make the
	// asteroids move faster as they get smaller. Increasing the constant multiplier
	// also serves to increase the speed of omvement.
	cpVect randDisplacement = cpvmult(cpv(sin(ang), cos(ang)), 500.0f*(INITIAL_ASTEROID_SPLIT_COUNT-splitCount+1));
	cpBodyApplyImpulse(asteroidBody, randDisplacement, cpvzero);
	
	asteroidCount++;
}

static void newAsteroidAtRandomPosition(int splitCount) {
	CGSize wins = [[CCDirector sharedDirector] winSize];
	
	cpFloat asteroidRadius = 7.0f*splitCount + (cpFloat)(rand()%4);
	
	// Randomly place the asteroid on the screen, but not on top of the ship...
	cpVect pos;
	while (YES) {
		// Place the asteroid in the space at the edge of the screen...
		pos = cpv((cpFloat)(rand()%(int)wins.width), (cpFloat)(rand()%(int)wins.height));
		NSLog(@"newAsteroid pos<x,y> <%f,%f>  ship<x,y> <%f,%f>\n", pos.x, pos.y, shipBody->p.x, shipBody->p.y);
		// The asteroid should not be created on top of the ship
		if (((shipBody->p.x < pos.x - asteroidRadius-15.0f) || (shipBody->p.x > pos.x + asteroidRadius+15.0f)) &&
			((shipBody->p.y < pos.y - asteroidRadius-15.0f) || (shipBody->p.y > pos.y + asteroidRadius+15.0f))) {
			NSLog(@"newAsteroid OK pos<x,y> <%f,%f>\n", pos.x, pos.y);
			break;
		}
	}
	newAsteroid(splitCount, pos);
}


////
//// Chipmunk Physics colission callbacks...
////

// Begin: Two shapes just started touching for the first time this step. Return true from the callback to process the collision
// normally or false to cause Chipmunk to ignore the collision entirely. If you return false, the pre-solve and post-solve
// callbacks will never be run, but you will still recieve a separate event when the shapes stop overlapping.
static int beginShipHitAsteroid(cpArbiter *arb, cpSpace *sp __attribute__ ((unused)), void *data __attribute__ ((unused))) {
	NSLog(@"shipHitAsteroid!!!\n");

	// Returning 0 will cause the collision to be discarded. This allows you to do conditional collisions.
	return 1;
}

// Remove the shape and associated body from the space...
static void removeFromSpace(cpSpace *sp, cpShape *shape) {
	cpSpaceRemoveBody(sp, shape->body);
	cpBodyFree(shape->body);
	
	cpSpaceRemoveShape(sp, shape);
	cpShapeFree(shape);	
}

static void postStepDistroyMissile(cpSpace *sp, cpShape *ms, void *data __attribute__ ((unused))) {
	// The problem is that the missile can be descroyed in a collision and by time expiration
	// Here, we assume that if the address of the shape is not in our array, then it has been destroyed.
	// It seems that the documentation in Chupmunk isn't correct about only processing one object once.
	NSLog(@"postStepDistroyMissile!");
	for (int i=0; i<MAX_MISSILES; i++)
		if (missileShape[i] == ms) {
			removeFromSpace(space, ms);
			missileShape[i] = (cpShape *)NULL;
			NSLog(@"  i = %d", i);
			break;
		}
}

// This is a "post step callback". Is scheduled from within a "collision handler" to modify the space.
// In Chipmunk Physics you are prohibited from modifying the space during colission detection.
static void postStepDistroyAsteroid(cpSpace *sp, cpShape *asteroidShape, void *data __attribute__ ((unused))) {
	NSLog(@"postStepDistroyAsteriud!\n");
	// Number of times that the asteroid can be shot and split before going away
	int splitCount = (int)asteroidShape->data - 1;
	// Position of the asteroid
	cpVect asteroidPosition = asteroidShape->body->p;
	
	if (splitCount > 0) {
		// Make 2 new asteroids with the decremented split count. They should be placed near to
		// where the current asteroid was located, possibly within that asteroid's radius.
		
		cpFloat ang = rand()%6;
		cpVect randDisplacement = cpvmult(cpv(sin(ang), cos(ang)), 7.0f*splitCount);
		newAsteroid(splitCount, cpvadd(asteroidPosition, randDisplacement));
		
		ang = rand()%6; // should be M_PI*2
		randDisplacement = cpvmult(cpv(sin(ang), cos(ang)), 7.0f*splitCount);
		newAsteroid(splitCount, cpvadd(asteroidPosition, randDisplacement));
	}
	
	if (asteroidShape->body->data) freeDrawablePolyShape((drawablePolyShape *)asteroidShape->body->data);
	removeFromSpace(sp, asteroidShape); // will be replaced by two smaller others
	
	asteroidCount--;
}

// Handler called by Chipmunk Physics when it detects a collision between two registered objects.
// In this case a Missile and an Asterois.
static int beginMissileHitAsteroid(cpArbiter *arb, cpSpace *sp, void *data __attribute__ ((unused))) {
	NSLog(@"missileHitAsteroid!!!\n");

	// Add code here to break up the asteroid if it's hasn't reached it's smallest size (in this
	// case remove it). Quite important to note that you need to use 'post-step' callbacks to add or remove
	// objects from the space. You CAN"T do it in a callback like this one. see...
	// http://files.slembcke.net/chipmunk/release/ChipmunkLatest-Docs/examples.html#CollisionCallbacks
	
	// Get the cpShapes involved in the collision
	// The order will be the same as you defined in the handler definition
	cpShape *ms, *as; cpArbiterGetShapes(arb, &ms, &as);

	// Add a post step callback to safely remove the body and shape from the space.
	// Calling cpSpaceRemove*() directly from a collision handler callback can cause crashes.
	// You can only register one post step callback per object. 
	cpSpaceAddPostStepCallback(space, (cpPostStepFunc)postStepDistroyAsteroid, as, NULL);
	cpSpaceAddPostStepCallback(space, (cpPostStepFunc)postStepDistroyMissile, ms, NULL);
	
	// The object is dead, don't process the collision further
	return 0;
}



////
//// Class implementation....
////

@implementation AsteroidsLayer


- (id)init
{
	// This is the usual way to start an init methid. Defer to the super class(the
	// one that we specialized), and it there was no failure creating it continue on...
	if ((self=[super init])) {
		
		self.isTouchEnabled = YES;
		self.isAccelerometerEnabled = YES;
		
		// Before you do anything else, you must initialize Chipmunk.
		// Otherwise you will crash as soon as the first collision is detected.
		cpInitChipmunk();

		// Spaces are the basic simulation unit in Chipmunk.
		// You add bodies, shapes and joints to a space, and then update the space as a whole.
		space = cpSpaceNew(); // this is a global
		// Define a gravity vector... 
		// There is no gravitational "pull" in this space, so things don't tend to fall down (or up for that matter).
		space->gravity = cpvzero;
		
		// Create the ship in the middle of the screen...
		newShip();
		
		// Initialize the structure used for the missles...
		for (int i=0; i<MAX_MISSILES; i++) missileShape[i] = NULL;
		
		// Add a collision handler for given collision type pair. Whenever a shapes with collision type (cpShape.collision_type)
		// a and collision type b collide, these callbacks will be used to process the collision. data is a user definable context
		// pointer that is passed to each of the callbacks. NULL can be provided for callbacks you do not wish to implement, however
		// Chipmunk will call it’s own default versions for these and not the default ones you’ve set up for the space.
		//
		// Note: we are only interested in the 'begin' handler, and not in the 'pre-solve', 'post-solve', and 'separate' handlers.
		cpSpaceAddCollisionHandler(space, kColl_Ship, kColl_Asteroid, &beginShipHitAsteroid, NULL, NULL, NULL, NULL);
		cpSpaceAddCollisionHandler(space, kColl_Missile, kColl_Asteroid, &beginMissileHitAsteroid, NULL, NULL, NULL, NULL);
		
		// Make the initial asteroids...
		asteroidCount = 0;
		for (int i=0; i<[[ApplicationData shared] initialAsteroidCount]; i++)
			newAsteroidAtRandomPosition(INITIAL_ASTEROID_SPLIT_COUNT);
		
		// Start the simulation...
		[self schedule: @selector(step:)];
	}
	
	return self;
}

- (void)dealloc
{ 
	NSLog(@"AsteroidsLayer dealloc\n");
	// Deallocate heap storage here....
	
	// Free things that we have attached to, the bodies.
	cpSpaceEachBody(space, freeDrawablePolyShapeInBody, NULL);
	// this will free the bodies, shapes, constraints associated with the space.
	cpSpaceFreeChildren(space);
	cpSpaceFree(space);
    
    [super dealloc];
}

//
// This method is a periodic callback scheduled at the bottom of the 'init' method
// for this class. On every frame of the animation, the cocos2d library will call
// this method. Here we use chipmunk Physics to move things around, check for collisions.
// We also use the time nature of this method to give a life time to each missile
// that is fired.
- (void)step: (ccTime)delta
{
	int steps = 2;
	CGFloat dt = delta/(CGFloat)steps;
	
	for (int i=0; i<steps; i++) {
		cpSpaceStep(space, dt);
	}
	
	// A missile is removed from the space if it is over a certain age (measured in simulation steps).
	// This code looks at all of the existing missils, ages them, and removes them if they have expired.
	for (int i=0; i<MAX_MISSILES; i++)
		if (missileShape[i] != NULL) {
			// There is a missile in this space...
			cpShape *ms = missileShape[i];
			if (--ms->data <= 0) {
				// It's time to destroy the missile...
				cpSpaceAddPostStepCallback(space, (cpPostStepFunc)postStepDistroyMissile, ms, NULL);
			}
		}
}

//
// onEnter and onExit are a part of the CCNode Scene Management (this is a CCLayer) in cocod2d.
// They are used for setting up and breaking down actions in the layer.

// -onEnter is called when a CCNode is added to a running Scene (or any child of one).
// Here we add a targeted touch delegate to the dispatcher's list.
- (void)onEnter {
	[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
	[[UIAccelerometer sharedAccelerometer] setUpdateInterval:(1.0 / 60)];
	[super onEnter];
}

// -onExit is when a CCHode is taken out of a running Scene.
- (void)onExit {
	[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
	[super onExit];
}


///
///
/// Cocos2d Handle Touches
///
/// For this to work this object must implement the 'CCTargetedTouchDelegate' Protocol, AND
/// call the 'addTargetedDelegate' method (see onEnter, and onExit).
///
/// A screen tap is seen as {Begin, End}.
/// A swipe is seen as {Begin, Moved, ...., End}.
///
/// Ship Control...
/// 1) A single tap fires a missle.
/// 2) A swipe causes the ship to point to where your finger is.
/// 3) A tap(s) at the same point where a swipe ended fires the thrusters (accelerates the ship).
///

// Was the finger moved during this interaction...
BOOL touchMoved = NO;

// Invoked when the finger first hits the screen...
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
	CGPoint loc = [touch locationInView: [touch view]];
	loc = [[CCDirector sharedDirector] convertToGL: loc];
	NSLog(@"ccTouchBegin loc <x,y> <%f,%f>\n", loc.x, loc.y);
	
	touchMoved = NO;
	
	// Return YES to claim the touch.
	return YES;
}

// Invoked when the finger is moved on the screen...
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event {
	CGPoint loc = [touch locationInView: [touch view]];
	loc = [[CCDirector sharedDirector] convertToGL: loc];
	NSLog(@"ccTouchMoved loc <x,y> <%f,%f>\n", loc.x, loc.y);
	
	// Zero both the forces and torques accumulated on body.
	//
	// The problem with not doing this HERE is that if the ship is spinning when you
	// finish the move you will not be able to generate a thrust in the direction that
	// the ship is in when it finished the move, because it will have spun some (angle will
	// be different), and we don't save this angle to use when activating the thrusters.
	// We could try saving this angle and using it for the thrusters.
	shipBody->v = shipBody->f = cpvzero;
	shipBody->a = shipBody->w = shipBody->t = 0.0f;

	// Rotate the ship to where the finger is relative to the bow ship (e.g., the bow should follow the finger).
	cpVect p = shipBody->p;
	// To find the angle between the line defined by the points 'shipBody->p' and 'lov' and the horizontal axis:
	double angle = atan2(p.y - loc.y, p.x - loc.x);	
	cpBodySetAngle(shipBody, angle);
	
	touchMoved = YES;
}

// Invoked when the finger leaves the screen...
- (void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
	CGPoint loc = [touch locationInView: [touch view]];
	loc = [[CCDirector sharedDirector] convertToGL: loc];
	cpVect p = shipBody->p;
	NSLog(@"ccTouchEnded shipBody <x,y>  <%f,%f>  loc <x,y> <%f,%f> touchMoved %@\n", p.x, p.y, loc.x, loc.y, (touchMoved ? @"Y" : @"N"));
	
	// If there was a "move" during this touch, then  fire the thrusters, otherwise fire a missle
	if (touchMoved) {
		// If the touch was near the last [end] touch then we fire the thrusters,
		// otherwise, we fire a missile.
		NSLog(@"Thrusters...\n");
		cpVect shipAngleVector = cpvforangle(shipBody->a);
		//cpVect shipAngleVector = cpv(cos(shipBody->a),sin(shipBody->a));
			
		// Note that the magnitude of the thrust needs to be based on the mass of the object
		// being moved
		cpFloat thrustMagnitude = SHIP_MASS * THRUST_MULTIPLIER;
		cpBodyApplyImpulse(shipBody, cpvmult(shipAngleVector, thrustMagnitude), cpvzero);
			
	} else {
		// then fire a missle...
		NSLog(@"Missile...\n");
		fireMissile();
	}
}

///
///
/// Drawing using openGLES (vector graphics) primitives...
///
///

static void drawCircleShape(cpShape *shape) {
	cpBody *body = shape->body;
	cpCircleShape *circle = (cpCircleShape *)shape;
	cpVect c = cpvadd(body->p, cpvrotate(circle->c, body->rot));
#define DRAWCIRCLE_SEGMENTS					(25)
#define DRAWCIRCLE_LINE_TO_CENTER			(NO)
	ccDrawCircle(ccp(c.x, c.y), circle->r, body->a, DRAWCIRCLE_SEGMENTS, DRAWCIRCLE_LINE_TO_CENTER);
    // !important this number changes the quality of circles
}

static void drawSegmentShape(cpShape *shape) {
	cpBody *body = shape->body;
	cpSegmentShape *seg = (cpSegmentShape *)shape;
	cpVect a = cpvadd(body->p, cpvrotate(seg->a, body->rot));
	cpVect b = cpvadd(body->p, cpvrotate(seg->b, body->rot));
	ccDrawLine(ccp(a.x, a.y), ccp(b.x, b.y));
}

static void drawPolyShape(cpBody *body) {
	
	drawablePolyShape *poly = (drawablePolyShape *)body->data;
	int num = poly->numVerts;
	cpVect *verts = poly->verts;
	
	// Bodies can be rotated. The drawable poly shape myst have the rotation
	// applied to it here before it is drawn...
	float *vertices = malloc(sizeof(float)*2*poly->numVerts);
	if(!vertices) return;
	
	for(int i=0; i<num; i++){
		cpVect v = cpvadd(body->p, cpvrotate(verts[i], body->rot));
		vertices[i*2] = v.x;
		vertices[i*2+1] = v.y;
	}
#define DRAWPOLY_CLOSE_POLYGON				(YES)
	ccDrawPoly((CGPoint *)vertices, poly->numVerts, DRAWPOLY_CLOSE_POLYGON);
	
	free(vertices);
}

static void drawShape(void *ptr, void *unused __attribute__ ((unused))) {
	cpShape *shape = (cpShape *)ptr; // This is the collision shape...
	cpBody *body = shape->body;		// the body associated with that shape
	
	// This is the code that keeps objects within the screen.
	// If an object moves to the edge of the screen it will be positioned
	// on the opposite side of the screen. This makes it "dissapear"
	// and then "reappear" when it's center point hits the screen boundries.
	// Making it appear on both sides would be much harder because you would
	// need to keep track of two objects for awhile, and delete the first
	// object when it completely exited the screen.
	CGSize wins = [[CCDirector sharedDirector] winSize];
	if (0.0f > body->p.x) body->p.x = wins.width;
	if (body->p.x > wins.width) body->p.x = 0.0f;
	if (0.0f > body->p.y) body->p.y = wins.height;
	if (body->p.y > wins.height) body->p.y = 0.0f;
	
	// It can have a different colour depending on what it is...
	switch(shape->collision_type){
		case kColl_Missile:
			glColor4f(1.0f, 0.0f, 0.0f, 1.0f); // RGBA
			drawCircleShape(shape);
			break;
		case kColl_Ship:
			glColor4f(0.0f, 1.0f, 0.0f, 0.8f);
			drawPolyShape(body);
			break;
		case kColl_Asteroid:
			glColor4f(0.0f, 0.0f, 1.0f, 0.8f);
			drawPolyShape(body);
			break;
		default:
            NSLog(@"Bad enumeration in drawObject().\n");
	}
}

// Every CocosNode has a "draw" method.
// In the "draw" method you put all the code that actually draws your node.
// This method must be specialized, the default one does nothing.
- (void)draw {
	cpSpaceHashEach(space->activeShapes, &drawShape, NULL);
	cpSpaceHashEach(space->staticShapes, &drawShape, NULL);
}

@end
